#include "Renderer_PCH.h"
#include "RendererStorageMgr.h"

/*--------------------------------------------------------------------------*/

RendererStorageMgr::RendererStorageMgr()
{
	m_blendStates_mutex			= g_Kernel->CreateNewMutex();
	m_rasterizerStates_mutex	= g_Kernel->CreateNewMutex();
	m_depthstencilStates_mutex	= g_Kernel->CreateNewMutex();
	m_samplerStates_mutex		= g_Kernel->CreateNewMutex();
	m_materials_mutex			= g_Kernel->CreateNewMutex();
	m_consts_mutex				= g_Kernel->CreateNewMutex();
	m_textures_mutex			= g_Kernel->CreateNewMutex();
	m_framebuffers_mutex		= g_Kernel->CreateNewMutex();
	m_buffers_mutex				= g_Kernel->CreateNewMutex();
	m_vertexarrays_mutex		= g_Kernel->CreateNewMutex();
	m_fonts_mutex				= g_Kernel->CreateNewMutex();
}

/*--------------------------------------------------------------------------*/

RendererStorageMgr::~RendererStorageMgr()
{

	m_blendStates_mutex->Lock();
	for (auto iter = m_blendStates.begin(); iter != m_blendStates.end(); ++iter)
		delete iter->second;

	m_blendStates.clear();
	m_blendStates_mutex->Unlock();
	delete m_blendStates_mutex;

	/*--------------------------------------------------------------------------*/

	m_depthstencilStates_mutex->Lock();
	for (auto iter = m_depthstencilStates.begin(); iter != m_depthstencilStates.end(); ++iter)
		delete iter->second;

	m_depthstencilStates.clear();
	m_depthstencilStates_mutex->Unlock();
	delete m_depthstencilStates_mutex;

	/*--------------------------------------------------------------------------*/

	m_rasterizerStates_mutex->Lock();
	for (auto iter = m_rasterizerStates.begin(); iter != m_rasterizerStates.end(); ++iter)
		delete iter->second;

	m_rasterizerStates.clear();
	m_rasterizerStates_mutex->Unlock();
	delete m_rasterizerStates_mutex;

	/*--------------------------------------------------------------------------*/

	m_samplerStates_mutex->Lock();
	for (auto iter = m_samplerStates.begin(); iter != m_samplerStates.end(); ++iter)
		delete iter->second;

	m_samplerStates.clear();
	m_samplerStates_mutex->Unlock();
	delete m_samplerStates_mutex;

	/*--------------------------------------------------------------------------*/

	m_consts_mutex->Lock();
	for (auto iter = m_consts.begin(); iter != m_consts.end(); ++iter)
		delete iter->second;	

	m_consts.clear();
	m_consts_mutex->Unlock();
	delete m_consts_mutex;

	/*--------------------------------------------------------------------------*/

	m_materials_mutex->Lock();
	for (auto iter = m_materials.begin(); iter != m_materials.end(); ++iter)
		delete iter->second;	

	m_materials.clear();
	m_materials_mutex->Unlock();
	delete m_materials_mutex;

	/*--------------------------------------------------------------------------*/

	m_textures_mutex->Lock();
	for (auto iter = m_textures.begin(); iter != m_textures.end(); ++iter)
		delete iter->second;	

	m_textures.clear();
	m_textures_mutex->Unlock();
	delete m_textures_mutex;

	/*--------------------------------------------------------------------------*/

	m_framebuffers_mutex->Lock();
	for (auto iter = m_framebuffers.begin(); iter != m_framebuffers.end(); ++iter)
		delete iter->second;	

	m_framebuffers.clear();
	m_framebuffers_mutex->Unlock();
	delete m_framebuffers_mutex;

	/*--------------------------------------------------------------------------*/

	m_buffers_mutex->Lock();
	for (auto iter = m_buffers.begin(); iter != m_buffers.end(); ++iter)
		delete iter->second;	

	m_buffers.clear();
	m_buffers_mutex->Unlock();
	delete m_buffers_mutex;

	/*--------------------------------------------------------------------------*/

	m_vertexarrays_mutex->Lock();
	for (auto iter = m_vertexarrays.begin(); iter != m_vertexarrays.end(); ++iter)
		delete iter->second;	

	m_vertexarrays.clear();
	m_vertexarrays_mutex->Unlock();
	delete m_vertexarrays_mutex;

	/*--------------------------------------------------------------------------*/

	m_fonts_mutex->Lock();
	for (auto iter = m_fonts.begin(); iter != m_fonts.end(); ++iter)
		delete iter->second;	

	m_fonts.clear();
	m_fonts_mutex->Unlock();
	delete m_fonts_mutex;
}

/*--------------------------------------------------------------------------*/

void RendererStorageMgr::InitRendererStorage()
{

}

/*--------------------------------------------------------------------------*/


RBlendState* RendererStorageMgr::CreateBlendState( const std::string& name )
{
	m_blendStates_mutex->Lock();
	auto iter = m_blendStates.find(name);

	if (iter == m_blendStates.end())
	{
		RBlendState* state = new RBlendState();
		m_blendStates[name] = state;

		m_blendStates_mutex->Unlock();
		return state;
	}
	else
	{
		m_blendStates_mutex->Unlock();
		__Crash("BlendState already exists!");
		return NULL;
	}
}

/*--------------------------------------------------------------------------*/

RRasterizerState* RendererStorageMgr::CreateRasterizerState( const std::string& name )
{
	m_rasterizerStates_mutex->Lock();
	auto iter = m_rasterizerStates.find(name);

	if (iter == m_rasterizerStates.end())
	{
		RRasterizerState* state = new RRasterizerState();
		m_rasterizerStates[name] = state;

		m_rasterizerStates_mutex->Unlock();
		return state;
	}
	else
	{
		m_rasterizerStates_mutex->Unlock();
		__Crash("RasterizerState already exists!");
		return NULL;
	}
}

/*--------------------------------------------------------------------------*/

RDepthstencilState* RendererStorageMgr::CreateDepthstencilState( const std::string& name )
{
	m_depthstencilStates_mutex->Lock();
	auto iter = m_depthstencilStates.find(name);

	if (iter == m_depthstencilStates.end())
	{
		RDepthstencilState* state = new RDepthstencilState();
		m_depthstencilStates[name] = state;

		m_depthstencilStates_mutex->Unlock();
		return state;
	}
	else
	{
		m_depthstencilStates_mutex->Unlock();
		__Crash("DepthstencilState already exists!");
		return NULL;
	}
}

/*--------------------------------------------------------------------------*/

RSamplerState* RendererStorageMgr::CreateSamplerState( const std::string& name )
{
	m_samplerStates_mutex->Lock();
	auto iter = m_samplerStates.find(name);

	if (iter == m_samplerStates.end())
	{
		RSamplerState* state = new RSamplerState();
		m_samplerStates[name] = state;

		m_samplerStates_mutex->Unlock();
		return state;
	}
	else
	{
		m_samplerStates_mutex->Unlock();
		__Crash("SamplerState already exists!");
		return NULL;
	}
}

/*--------------------------------------------------------------------------*/

RConst* RendererStorageMgr::CreateConst( const std::string& name, EConst::Type type, uint size, IConstUpdater* updater, uint arg )
{
	m_consts_mutex->Lock();
	auto iter = m_consts.find(name);

	if (iter == m_consts.end())
	{
		RConst* constant = new RConst(type, size);
		constant->m_constUpdater = updater;
		constant->m_constUpdaterArg = arg;

		m_consts[name] = constant;

		switch (type)
		{
		case EConst::Float1:
			{
				*((float*)constant->GetPointer()) = 0.0f;
				break;
			}
		case EConst::Float4:
			{
				*((glm::vec4*)constant->GetPointer()) = glm::vec4(0.0f, 0.0f, 0.0f, 0.0f);
				break;
			}
		case EConst::Int4:
			{
				*((glm::ivec4*)constant->GetPointer()) = glm::ivec4(0, 0, 0, 0);
				break;
			}
		case EConst::Mat4:
			{
				*((glm::mat4*)constant->GetPointer()) = glm::mat4();
				break;
			}
		}

		m_consts_mutex->Unlock();
		return constant;
	}
	else
	{
		m_consts_mutex->Unlock();
		__Crash("Shader already exists!");
		return NULL;
	}
}

/*--------------------------------------------------------------------------*/

RMaterial* RendererStorageMgr::CreateMaterial( const std::string& name )
{
	m_materials_mutex->Lock();
	auto iter = m_materials.find(name);

	if (iter == m_materials.end())
	{
		RMaterial* material = new RMaterial(name);
		m_materials[name] = material;

		m_materials_mutex->Unlock();
		return material;
	}
	else
	{
		m_materials_mutex->Unlock();
		__Crash("Material already exists!");
		return NULL;
	}
}

/*--------------------------------------------------------------------------*/

RTexture* RendererStorageMgr::CreateTexture( const std::string& name )
{
	m_textures_mutex->Lock();
	auto iter = m_textures.find(name);

	if (iter == m_textures.end())
	{
		RTexture* texture = new RTexture(name);
		m_textures[name] = texture;

		m_textures_mutex->Unlock();
		return texture;
	}
	else
	{
		m_textures_mutex->Unlock();
		__Crash("Texture already exists!");
		return NULL;
	}
}

/*--------------------------------------------------------------------------*/

RFramebuffer* RendererStorageMgr::CreateFramebuffer( const std::string& name )
{
	m_framebuffers_mutex->Lock();
	auto iter = m_framebuffers.find(name);

	if (iter == m_framebuffers.end())
	{
		RFramebuffer* framebuffer = new RFramebuffer();
		m_framebuffers[name] = framebuffer;

		m_framebuffers_mutex->Unlock();
		return framebuffer;
	}
	else
	{
		m_framebuffers_mutex->Unlock();
		__Crash("Framebuffer already exists!");
		return NULL;
	}
}

/*--------------------------------------------------------------------------*/

RBuffer* RendererStorageMgr::CreateBuffer( const std::string& name, uint size, bool dynamic, uint type )
{
	m_buffers_mutex->Lock();
	auto iter = m_buffers.find(name);

	if (iter == m_buffers.end())
	{
		RBuffer* buffer = new RBuffer(size, dynamic, type);
		m_buffers[name] = buffer;

		m_buffers_mutex->Unlock();
		return buffer;
	}
	else
	{
		m_buffers_mutex->Unlock();
		__Crash("Buffer already exists!");
		return NULL;
	}
}

/*--------------------------------------------------------------------------*/

RVertexArray* RendererStorageMgr::CreateVertexArray( const std::string& name )
{
	m_vertexarrays_mutex->Lock();
	auto iter = m_vertexarrays.find(name);

	if (iter == m_vertexarrays.end())
	{
		RVertexArray* vertexarray = new RVertexArray(name);
		m_vertexarrays[name] = vertexarray;

		m_vertexarrays_mutex->Unlock();
		return vertexarray;
	}
	else
	{
		m_vertexarrays_mutex->Unlock();
		__Crash("VertexArray already exists!");
		return NULL;
	}
}

/*--------------------------------------------------------------------------*/

RFont* RendererStorageMgr::CreateFont( const std::string& name )
{
	m_fonts_mutex->Lock();
	auto iter = m_fonts.find(name);

	if (iter == m_fonts.end())
	{
		RFont* font = new RFont();
		m_fonts[name] = font;

		m_fonts_mutex->Unlock();
		return font;
	}
	else
	{
		m_fonts_mutex->Unlock();
		__Crash("Font already exists!");
		return NULL;
	}
}

/*--------------------------------------------------------------------------*/

RBlendState* RendererStorageMgr::GetBlendState( const std::string& name )
{
	m_blendStates_mutex->Lock();
	auto iter = m_blendStates.find(name);

	if (iter == m_blendStates.end())
	{
		m_blendStates_mutex->Unlock();
		return NULL;
	}
	else
	{
		RBlendState* q = iter->second;
		m_blendStates_mutex->Unlock();
		return q;
	}
}

/*--------------------------------------------------------------------------*/

RRasterizerState* RendererStorageMgr::GetRasterizerState( const std::string& name )
{
	m_rasterizerStates_mutex->Lock();
	auto iter = m_rasterizerStates.find(name);

	if (iter == m_rasterizerStates.end())
	{
		m_rasterizerStates_mutex->Unlock();
		return NULL;
	}
	else
	{
		RRasterizerState* q = iter->second;
		m_rasterizerStates_mutex->Unlock();
		return q;
	}
}

/*--------------------------------------------------------------------------*/

RDepthstencilState* RendererStorageMgr::GetDepthstencilState( const std::string& name )
{
	m_depthstencilStates_mutex->Lock();
	auto iter = m_depthstencilStates.find(name);

	if (iter == m_depthstencilStates.end())
	{
		m_depthstencilStates_mutex->Unlock();
		return NULL;
	}
	else
	{
		RDepthstencilState* q = iter->second;
		m_depthstencilStates_mutex->Unlock();
		return q;
	}
}

/*--------------------------------------------------------------------------*/

RSamplerState* RendererStorageMgr::GetSamplerState( const std::string& name )
{
	m_samplerStates_mutex->Lock();
	auto iter = m_samplerStates.find(name);

	if (iter == m_samplerStates.end())
	{
		m_samplerStates_mutex->Unlock();
		return NULL;
	}
	else
	{
		RSamplerState* q = iter->second;
		m_samplerStates_mutex->Unlock();
		return q;
	}
}

/*--------------------------------------------------------------------------*/

RConst* RendererStorageMgr::GetConst( const std::string& name )
{
	m_consts_mutex->Lock();
	auto iter = m_consts.find(name);

	if (iter == m_consts.end())
	{
		m_consts_mutex->Unlock();
		return NULL;
	}
	else
	{
		RConst* q = iter->second;
		m_consts_mutex->Unlock();
		return q;
	}
}

/*--------------------------------------------------------------------------*/

RMaterial* RendererStorageMgr::GetMaterial( const std::string& name )
{
	m_materials_mutex->Lock();
	auto iter = m_materials.find(name);

	if (iter == m_materials.end())
	{
		m_materials_mutex->Unlock();
		return NULL;
	}
	else
	{
		RMaterial* q = iter->second;
		m_materials_mutex->Unlock();
		return q;
	}
}

/*--------------------------------------------------------------------------*/

RTexture* RendererStorageMgr::GetTexture( const std::string& name )
{
	m_textures_mutex->Lock();
	auto iter = m_textures.find(name);

	if (iter == m_textures.end())
	{
		m_textures_mutex->Unlock();
		return NULL;
	}
	else
	{
		RTexture* q = iter->second;
		m_textures_mutex->Unlock();
		return q;
	}
}

/*--------------------------------------------------------------------------*/

RFramebuffer* RendererStorageMgr::GetFramebuffer( const std::string& name )
{
	m_framebuffers_mutex->Lock();
	auto iter = m_framebuffers.find(name);

	if (iter == m_framebuffers.end())
	{
		m_framebuffers_mutex->Unlock();
		return NULL;
	}
	else
	{
		RFramebuffer* q = iter->second;
		m_framebuffers_mutex->Unlock();
		return q;
	}
}

/*--------------------------------------------------------------------------*/

RBuffer* RendererStorageMgr::GetBuffer( const std::string& name )
{
	m_buffers_mutex->Lock();
	auto iter = m_buffers.find(name);

	if (iter == m_buffers.end())
	{
		m_buffers_mutex->Unlock();
		return NULL;
	}
	else
	{
		RBuffer* q = iter->second;
		m_buffers_mutex->Unlock();
		return q;
	}
}

/*--------------------------------------------------------------------------*/

RVertexArray* RendererStorageMgr::GetVertexArray( const std::string& name )
{
	m_vertexarrays_mutex->Lock();
	auto iter = m_vertexarrays.find(name);

	if (iter == m_vertexarrays.end())
	{
		m_vertexarrays_mutex->Unlock();
		return NULL;
	}
	else
	{
		RVertexArray* q = iter->second;
		m_vertexarrays_mutex->Unlock();
		return q;
	}
}

/*--------------------------------------------------------------------------*/

RFont* RendererStorageMgr::GetFont( const std::string& name )
{
	m_fonts_mutex->Lock();
	auto iter = m_fonts.find(name);

	if (iter == m_fonts.end())
	{
		m_fonts_mutex->Unlock();
		return NULL;
	}
	else
	{
		RFont* q = iter->second;
		m_fonts_mutex->Unlock();
		return q;
	}
}

/*--------------------------------------------------------------------------*/

